1 /*
2 Copyright (c)
2014 Andrew Jones, Dario Seyb
3  Based
on 'Spriter2Unity' python code by Malhavok
4
5 Permission
is hereby granted, free of charge, to any person obtaining a copy
6 of
this software and associated documentation files (the "Software"), to deal
7 in
the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software
is
10 furnished to
do so, subject to the following conditions:
11
12 The above copyright notice and
this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED
"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 */

23
24 using
Assets.ThirdParty.Spriter2Unity.Editor.Spriter;
25 using
System.Reflection;
26 using
UnityEditor;
27 using
UnityEngine;
28
29 namespace
Assets.ThirdParty.Spriter2Unity.Editor.Spriter
30 {
31     
public static class AnimationCurveUtils
32     {
33         
public const float MIN_DELTA_TIME = 0.001f;
34         
public const bool ENABLE_KEYFRAME_REDUCATION = true;
35
36         
public static void AddKey(this AnimationCurve curve, Keyframe keyframe, TimelineKey lastKey)
37         {
38             
var keys = curve.keys;
39
40             
//Early out - if this is the first key on this curve just add it
41             
if (keys.Length == 0)
42             {
43                 curve.AddKey(keyframe);
44                 
return;
45             }
46
47             
if (lastKey == null)
48             {
49                 Debug.Log(
string.Format("ERROR: NULL lastkey passed to AddKey when curve contains {0} keys", keys.Length));
50                 
return;
51             }
52
53             
//Get the last keyframe
54             Keyframe lastKeyframe = keys[keys.Length -
1];
55
56             
//If no TimelineKey is supplied, default to Linear curve
57             CurveType curveType = lastKey.CurveType;
58
59             
switch (curveType)
60             {
61                 
case CurveType.Instant:
62                     lastKeyframe.outTangent =
0;
63                     curve.MoveKey(keys.Length -
1, lastKeyframe);
64
65                     keyframe.inTangent =
float.PositiveInfinity;
66                     curve.AddKey(keyframe);
67                     
break;
68
69                 
case CurveType.Linear:
70                     
var val = (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
71                     lastKeyframe.outTangent = val;
72                     curve.MoveKey(keys.Length -
1, lastKeyframe);
73
74                     keyframe.inTangent = val;
75                     curve.AddKey(keyframe);
76                     
break;
77
78                 
case CurveType.Quadratic:
79                     {
80                         
//Increase to cubic
81                         
var c1 = (2 * lastKey.CurveParams[0]) / 3;
82                         
var c2 = 1 - (2 * lastKey.CurveParams[0] + 1) / 3;
83
84                         
//Convert [0,1] into unity-acceptable tangents
85                         c1 *=
3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
86                         c2 *=
3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
87
88                         
//Set the out tangent for the previous frame and update
89                         lastKeyframe.outTangent = c1;
90                         curve.MoveKey(keys.Length -
1, lastKeyframe);
91
92                         
//Set the in tangent for the current frame and add
93                         keyframe.inTangent = c2;
94                         curve.AddKey(keyframe);
95                         
break;
96                     }
97
98                 
case CurveType.Cubic:
99                     {
100                         
//Get curve parameters
101                         
var c1 = lastKey.CurveParams[0];
102                         
var c2 = 1 - lastKey.CurveParams[1];
103
104                         
//Convert [0,1] into unity-acceptable tangents
105                         c1 *=
3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
106                         c2 *=
3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
107
108                         
//Set the out tangent for the previous frame and update
109                         lastKeyframe.outTangent = c1;
110                         curve.MoveKey(keys.Length -
1, lastKeyframe);
111
112                         
//Set the in tangent for the current frame and add
113                         keyframe.inTangent = c2;
114                         curve.AddKey(keyframe);
115                         
break;
116                     }
117
118                 
default:
119                     Debug.LogWarning(
"CurveType " + curveType.ToString() + " not yet supported!");
120                     
break;
121             }
122         }

123
124         ///
<summary>
125         ///
Add the specified key and set the in/out tangents for a linear curve
126         ///
</summary>
127         
public static void AddLinearKey(this AnimationCurve curve, Keyframe keyframe)
128         {
129             
var keys = curve.keys;
130             
//Second or later keyframe - make the slopes linear
131             
if (keys.Length > 0)
132             {
133                 
var lastFrame = keys[keys.Length - 1];
134                 
float slope = (keyframe.value - lastFrame.value) / (keyframe.time - lastFrame.time);
135                 lastFrame.outTangent = keyframe.inTangent = slope;
136
137                 
//Update the last keyframe
138                 curve.MoveKey(keys.Length -
1, lastFrame);
139             }
140
141             
//Add the new frame
142             curve.AddKey(keyframe);
143         }
144
145         
public static void AddKeyIfChanged(this AnimationCurve curve, Keyframe keyframe)
146         {
147             
var keys = curve.keys;
148             
//If this is the first key on this curve, always add
149             
//NOTE: Add TWO copies of the first frame, then we adjust the last frame as we move along
150             
//This guarantees a minimum of two keys in each curve
151             
if (keys.Length == 0 || !ENABLE_KEYFRAME_REDUCATION)
152             {
153                 curve.AddKey(keyframe);
154                 keyframe.time +=
float.Epsilon;
155                 curve.AddKey(keyframe);
156             }
157             
else
158             {
159                 
//TODO: This method of keyframe reduction causes artifacts in animations that are supposed to deliberately pause
160                 
//Find the last keyframe
161                 Keyframe lastKey = keys[keys.Length -
1];
162                 
if (lastKey.time >= keyframe.time)
163                     Debug.LogError(
"Keyframes not supplied in consecutive order!!!");
164
165                 
//Grab 2 frames ago
166                 
var last2Key = keys[keys.Length - 2];
167
168                 
//If the previous 2 frames were different, add a new frame
169                 
if (lastKey.value != last2Key.value)
170                 {
171                     curve.AddKey(keyframe);
172                 }
173                 
//The previous frame is redundant - just move it
174                 
else
175                 {
176                     curve.MoveKey(keys.Length -
1, keyframe);
177                 }
178             }
179         }
180
181         
/* Method Signature:
182         [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
183         
internal static extern void SetAnimationClipSettings(AnimationClip clip, AnimationClipSettings srcClipInfo);
184          */

185         ///
<summary>
186         ///
Uses reflection to call the internal (seriously, guys?!) SetAnimationClipSettings method
187         ///
Especially funny because the method doesn't even appear to be USED internally...
188         ///
</summary>
189         
public static void SetAnimationSettings(this AnimationClip animClip, AnimationClipSettings settings)
190         {
191             
//Use reflection to get the internal method
192             BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.NonPublic;
193             MethodInfo mInfo =
typeof(AnimationUtility).GetMethod("SetAnimationClipSettings", bindingFlags);
194             mInfo.Invoke(
null, new object[] { animClip, settings });
195         }
196     }
197 }


Early out - if this is the first key on this curve just add it

Get the last keyframe

If no TimelineKey is supplied, default to Linear curve

Increase to cubic

Convert [0,1] into unity-acceptable tangents

Set the out tangent for the previous frame and update

Set the in tangent for the current frame and add

Get curve parameters

Convert [0,1] into unity-acceptable tangents

Set the out tangent for the previous frame and update

Set the in tangent for the current frame and add

Add the specified key and set the inout tangents for a linear curve

Second or later keyframe - make the slopes linear

Update the last keyframe

Add the new frame

If this is the first key on this curve, always add

NOTE: Add TWO copies of the first frame, then we adjust the last frame as we move along

This guarantees a minimum of two keys in each curve

TODO: This method of keyframe reduction causes artifacts in animations that are supposed to deliberately pause

Find the last keyframe

Grab 2 frames ago

If the previous 2 frames were different, add a new frame

The previous frame is redundant - just move it

Uses reflection to call the internal (seriously, guys?!) SetAnimationClipSettings method

Especially funny because the method doesn't even appear to be USED internally...

Use reflection to get the internal method




Trò chơi đua xe động vật trong UNITY Engine 114.905 lượt xem

Gõ tìm kiếm nhanh...